package com.cloudkinto.service.file.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cloudkinto.common.common.Base64Util;
import com.cloudkinto.common.common.DateUtils;
import com.cloudkinto.common.common.FileUtils;
import com.cloudkinto.common.constant.GlobalConstants;
import com.cloudkinto.common.constant.SysConstant;
import com.cloudkinto.common.exception.BizException;
import com.cloudkinto.common.exception.BizExceptionI18;
import com.cloudkinto.common.utils.ali.AliOss;
import com.cloudkinto.common.web.SingleResult;
import com.cloudkinto.dao.FileDao;
import com.cloudkinto.dao.FileMoreDao;
import com.cloudkinto.entity.FileDo;
import com.cloudkinto.entity.FileMoreDo;
import com.cloudkinto.service.file.FileService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.BinaryHeap;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhangyy
 * @date 2020/5/27 12:35
 * @description:
 */
@Transactional(rollbackFor = Exception.class)//事务回滚
@Service
@Slf4j
public class FileServiceImpl extends ServiceImpl<FileDao, FileDo> implements FileService {

    //真正的存储路径
    @Value("${gbc.uploadPath.filePath}")
    private String filePath;
    //真正的存储路径
    @Value("${gbc.uploadPath.fileUrl}")
    private String fileUrl;

    //临时存储路径
    @Value("${gbc.uploadPath.filePathTemp}")
    private String filePathTemp;


    //对接外面图片存储路径
    @Value("${gbc.uploadPath.imagePath}")
    private String imagePath;

    @Autowired
    private FileDao fileDao;
    @Autowired
    private FileMoreDao fileMoreDao;

    @Override
    public SingleResult uploadTempFile(MultipartFile file, Long userId) {
        if (file.isEmpty()) {
            throw new BizExceptionI18(SysConstant.File_Pls_Choose);
        }
        String fileName = file.getOriginalFilename();//获取文件名
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);//获取文件后缀
        if (fileName.length() > 80) {
            fileName = fileName.substring(fileName.length() - 80);
        }
        if (!GlobalConstants.FILE_SUFFIX.contains(suffix)) {
            throw new BizExceptionI18(SysConstant.File_No_Support , GlobalConstants.FILE_SUFFIX );
        }
        //添加记录file表
        Long fileId = addFile(fileName, suffix, userId);
        if (filePath.startsWith("http")) {
            //添加到临时文件
            try {
                AliOss.temporaryFile(fileId, suffix, file);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            upload(file, suffix, fileId);
        }

        Map map = new HashMap();
        map.put("fileId", fileId);
        return SingleResult.success(map);
    }

    @Override
    public Long uploadTempFile(String fileName, InputStream inputStream, Long userId) {
        //保存到t_file表中
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);//获取文件后缀
        if (fileName.length() > 80) {
            fileName = fileName.substring(fileName.length() - 80);
        }
        if (!GlobalConstants.FILE_SUFFIX.contains(suffix)) {
            return 0L;
        }
        Long fileId = addFile(fileName, suffix, userId);
        if (filePath.startsWith("http")) {
            //添加到临时文件
            try {
                AliOss.temporaryFile3(fileId, suffix, inputStream);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            FileUtils.make(filePathTemp);
            String path = filePathTemp + File.separator + fileId + "." + suffix;
            try {
                FileUtils.uploadFile(inputStream, path);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return fileId;
    }

    @Override
    public SingleResult uploadImage(String base64, String fileName) throws Exception {
        File file = new File(imagePath + fileName);
        if (file.exists()) {
            file.delete();
        }
        Base64Util.GenerateImage(base64, fileName, imagePath);
        return SingleResult.success();
    }

    @Override
    public SingleResult downLoadImage(String fileName) throws Exception {
        return SingleResult.success(imagePath + fileName);
    }

    @Override
    public void uploadFileMult(Long[] fileIds) {
        for (Long fileId :
                fileIds) {
            uploadFile(fileId);
        }
    }

    // 将修改前的fileId的存入

    @Override
    public void uploadFile(Long fileId) {
        if (fileId == null || fileId == 0) {
            return;
        }
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            throw new BizExceptionI18(SysConstant.File_Upload_Error);
        }
        if (!filePath.startsWith("http")) {
            //临时目录的文件
            File file = new File(filePathTemp + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix());
            if (!file.exists()) {
                return;
            }

            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream(file);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
                return;
            }
            //创建文件目录  避免原本真正目录不存在异常
            File dir = new File(filePath);
            if (!dir.exists() && !dir.isDirectory()) {
                dir.mkdirs();
            }
            //将临时目录的文件移到真正的目录
            FileUtils.uploadFile(fileInputStream, filePath + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix());
            file.delete();
        } else {
            //上传到阿里OSS 并删除临时保存的文件
            AliOss.uploadFile(AliOss.objectName + "temporaryFile/" + fileId + "." + fileDo.getFileSuffix(), fileDo.getFileSuffix(), fileDo.getId());
        }
    }

    @Override
    public void uploadFile2(Long fileId, Long oldFileId) {
        if (fileId == null || fileId == 0) {
            return;
        }
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            throw new BizExceptionI18(SysConstant.File_Upload_Error);
        }
        if (filePath.startsWith("http")) {
            //上传到阿里OSS 并删除临时保存的文件
            AliOss.uploadFile(AliOss.objectName + "temporaryFile/" + fileId + "." + fileDo.getFileSuffix(), fileDo.getFileSuffix(), fileDo.getId());
        } else {
            File file = new File(filePath + File.separator + oldFileId + "." + fileDo.getFileSuffix());
            if (file != null) {
                file.delete();
            }
            uploadFile(fileId);
        }
    }

    @Override
    public List<String> getFilePathMulti(String fileIds) {
        if (StringUtils.isEmpty(fileIds)) return new ArrayList<>();
        String[] strings = fileIds.split(",");
        List<String> paths = new ArrayList<>();
        for (String fileId :
                strings) {
            paths.add(getFilePath(Long.parseLong(fileId)));
        }
        return paths;
    }

    /**
     * 获取文件访问路径
     *
     * @param fileId
     * @return
     */
    @Override
    public String getFilePath(Long fileId) {
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            return null;
        }
        if (filePath.startsWith("http")) {
            //对时间处理
//            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
//            String date = simpleDateFormat.format(fileDo.getCreateTime());
            String date = DateUtils.dateFormatToString(fileDo.getCreateTime(),"yyyyMM");
            //对文件类型进行处理
            if (GlobalConstants.IMG_SUFFIX.contains(fileDo.getFileSuffix())) {
                return fileUrl + date + "/photo/" + fileDo.getId() + "." + fileDo.getFileSuffix();
            }
            return fileUrl + date + "/document/" + fileDo.getId() + "." + fileDo.getFileSuffix();
        } else {
            return fileUrl + "/" + fileDo.getId() + "." + fileDo.getFileSuffix();
        }
    }


    //获得临时存储文件
    @Override
    public String getFilePathTemp(Long fileId) {
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            return null;
        }
        if (filePath.startsWith("http")) {
           // return AliOss.template + fileDo.getId() + "." + fileDo.getFileSuffix();
            return "https://cloudkinto-1.oss-cn-hangzhou.aliyuncs.com/cloudkint-file/temporaryFile"+ "/"+fileDo.getId()+"."+fileDo.getFileSuffix();
        } else {
            return fileUrl + "/" + fileDo.getId() + "." + fileDo.getFileSuffix();
        }
    }

    @Override
    public String getTemporaryFilePath(Long fileId) {
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            return null;
        }
        if (filePath.startsWith("http")) {
            return fileUrl + AliOss.temporaryFile + fileDo.getId() + "." + fileDo.getFileSuffix();
        }else {
            return fileUrl + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix();
        }
    }

    @Override
    public void deleteFileMulti(String fileIds) {
        String[] strings = fileIds.split(",");
        for (String fileId :
                strings) {
            if (StringUtils.isBlank(fileId)) {
                continue;
            }
            deleteFile(Long.parseLong(fileId));
        }
    }

    @Override
    public void deleteFile(Long fileId) {
        if (fileId == null || fileId == 0L) {
            return;
        }
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
            return;
        }
        if (filePath.startsWith("http")) {
            //得到原图路径  因为以前的数据所以需要判断
            String filePath = getFilePath(fileId);
            AliOss.deleteFile(filePath, fileDo.getFileSuffix(), fileDo.getId());
        } else {
            File file = new File(filePath + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix());
            if (file != null) {
                file.delete();
            }
        }
        fileDao.deleteById(fileId);
    }

    @Override
    public Long uploadExcelImage(String url, Long userId) throws FileNotFoundException {
        //FileUtils.make(filePathTemp);
        File file = new File(url);
        if (!file.exists()) return null;
        String fileName = file.getName();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);//获取文件后缀
        Long fileId = addFile(fileName, suffix, userId);
        //临时保存
        try {
            AliOss.temporaryFile2(fileId, suffix, file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //保存真实的
        AliOss.uploadFile(getFilePathTemp(fileId), suffix, fileId);
        file.delete();
        return fileId;
    }


    //将文件存储到临时目录
    private void upload(MultipartFile file, String suffix, Long fileId) {
        FileUtils.make(filePathTemp);
        String path = filePathTemp + File.separator + fileId + "." + suffix;
        try {
            FileUtils.uploadFile(file.getInputStream(), path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    private Long addFile(String fileName, String suffix, Long userId) {
        FileDo fileDo = new FileDo();
        fileDo.setCreateBy(userId);
        fileDo.setCreateTime(new Date());
        fileDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        fileDo.setFileName(fileName);
        fileDo.setFileSuffix(suffix);
        fileDao.insert(fileDo);
        return fileDo.getId();
    }

    public Long addFile(String fileName, Long userId) {
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1);//获取文件后缀
        if (suffix.length() > 8) {
            suffix = "jpg";
        }
        if (fileName.length() > 80) {
            fileName = fileName.substring(fileName.length() - 80);
        }
        FileDo fileDo = new FileDo();
        fileDo.setCreateBy(userId);
        fileDo.setCreateTime(new Date());
        fileDo.setDeleteFlag(SysConstant.DELETE_FLAG_FALSE);
        fileDo.setFileName(fileName);
        fileDo.setFileSuffix(suffix);
        fileDao.insert(fileDo);
        return fileDo.getId();
    }



    /**
     * 附件上传，二进制流直接上传到正式路径
     *
     * @param inputStream
     * @param fileName
     */
    @Override
    public Long uploadFileToFormalPath(InputStream inputStream, String fileName) {
        Long fileId = this.addFile(fileName, null);
        FileDo fileDo = fileDao.selectById(fileId);
        if (fileDo == null) {
//            throw new BizException("文件上传失败，请稍后再试！");
            return 0L;
        }
        if (!filePath.startsWith("http")) {
            //直接保存到本地正式路径
            FileUtils.uploadFile(inputStream, filePath + File.separator + fileDo.getId() + "." + fileDo.getFileSuffix());
        } else {
            //直接上传到阿里OSS
            AliOss.uploadFile(inputStream, fileDo.getFileSuffix(), fileId);
        }
        return fileId;
    }

    @Override
    public void addFileMoreDo(Long fileId, Long mailId, String type) {
        if (fileId != null && fileId != 0L) {
            FileMoreDo fileMoreDo = new FileMoreDo();
            fileMoreDo.setFileId(fileId);
            fileMoreDo.setMailId(mailId);
            fileMoreDo.setType(type);
            fileMoreDo.setCreateTime(new Date());
            fileMoreDao.insert(fileMoreDo);
        }
    }
}
